home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Everything For A Hacker
/
19990506-[HACK].iso
/
HEXEDIT
/
UTILS
/
EMSTULKT.ARJ
/
DISK1.EXE
/
lha
/
MEMLIB.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-12-01
|
89KB
|
1,760 lines
/**********************************************************************/
/* */
/* Module: MEMLIB.C */
/* */
/* This module contains the C MEMORY MANAGER - a group of C */
/* callable routines that manage expanded memory. These */
/* routines alleviate many of the housekeeping chores necessary */
/* when dealing with expanded memory and make allocating and */
/* freeing expanded memory look as much like allocating and */
/* freeing conventional memory as possible. */
/* */
/* The routines called by an application are: */
/* */
/* ememavl Approximate amount of free expanded memory */
/* ememmax Size of the largest contiguous free block */
/* emsize Size of a specified block */
/* efmalloc Allocate a block of memory */
/* effree Free a previously allocated block */
/* seteptrs Access n different blocks */
/* set1eptr Access 1 block */
/* set2eptrs Access 2 blocks */
/* set3eptrs Access 3 blocks */
/* push_context Push the current mapping context */
/* pop_context Pop a mapping context */
/* effreeall Frees ALL blocks */
/* */
/**********************************************************************/
#include "memintrl.c"
/*$PAGE*/
/**********************************************************************/
/* */
/* Name: unsigned int ememavl (*size) */
/* unsigned long *size; */
/* */
/* Description: */
/* Computes the size of expanded memory available in bytes but */
/* due to memory fragmentation, the largest useable block may be */
/* smaller than the amount returned by this function. See */
/* ememmax. */
/* */
/* Parameters: */
/* output size The size computed. */
/* */
/* Results returned: */
/* PASSED The size is valid */
/* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
/* */
/* Calling sequence: */
/* #include "memlib.h" */
/* #include "errors.h" */
/* ... */
/* unsigned long size; */
/* unsigned int status; */
/* ... */
/* status = ememavl (&size); */
/* if (status == PASSED) */
/* printf("Expanded memory available = %lu \n", size); */
/* else */
/* { error condition } */
/* */
/* Calls: prepare_dir_mapping() */
/* get_unalloc_page_count() */
/* restore_memlib_context() */
/* map_dir_page() */
/* */
/* Called by: Application */
/* */
/* Globals referenced/modified: directory */
/* dir_page_count */
/* */
/**********************************************************************/
unsigned int ememavl (size)
unsigned long *size;
{
unsigned int status; /* The status of EMM and MEMLIB */
unsigned int num_unalloc_pages; /* Number of unallocated pages */
unsigned int index; /* Index into a directory page */
unsigned int dir_page; /* The directory page to map in */
unsigned int context_saved; /* Whether the contexted was saved */
*size = 0;
/**********************************************/
/* Call prepare_dir_mapping() to save context */
/* before mapping in the directory. */
/**********************************************/
status = prepare_dir_mapping (&context_saved);
if (status == PASSED)
{
/********************************************************/
/* Add up the number of 16K pages that are unallocated. */
/********************************************************/
status = get_unalloc_page_count (&num_unalloc_pages);
if (status == PASSED)
{
*size += PAGE_SIZE * (long) num_unalloc_pages;
}
/***************************************************/
/* Go through entire directory one page at a time. */
/***************************************************/
for (dir_page = 0; ((status == PASSED) &&
(dir_page < dir_page_count)); dir_page++)
{
/***********************************/
/* Map in the this directory page. */
/***********************************/
status = map_dir_page (dir_page, FIRST_PHYS_PAGE);
if (status == PASSED)
{
/******************************************/
/* Add up all freed blocks for this page. */
/******************************************/
for (index = 0; (index < DIR_ENTRIES_PER_PAGE); index++)
{
if (directory[0][index].token == UNASSIGNED_TOKEN)
*size += directory[0][index].size;
}
}
}
}
/**************************************************************/
/* Unmap the directory - remap the pages that were in before. */
/**************************************************************/
if (context_saved)
status = restore_memlib_context (status);
/*************************************/
/* If some error return a size of 0. */
/*************************************/
if (status != PASSED)
*size = 0;
return (status);
} /** end of ememavl **/
/*$PAGE*/
/**********************************************************************/
/* */
/* Name: unsigned int ememmax (*size) */
/* unsigned int *size; */
/* */
/* Description: */
/* Computes the size of the largest block of expanded memory */
/* that MEMLIB can allocate. */
/* */
/* Parameters: */
/* output size The size of the largest allocatable block. */
/* */
/* Results returned: */
/* PASSED Operation successful */
/* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
/* */
/* Calling sequence: */
/* #include "memlib.h" */
/* #include "errors.h" */
/* ... */
/* unsigned int size; */
/* unsigned int status; */
/* ... */
/* status = ememmax (&size); */
/* if (status == PASSED) */
/* printf("Largest block available = %u \n", size); */
/* else */
/* { error condition } */
/* */
/* Calls: prepare_dir_mapping() */
/* map_dir_page() */
/* get_unalloc_page_count() */
/* restore_memlib_context() */
/* */
/* Called by: Application */
/* */
/* Globals referenced/modified: directory */
/* dir_page_count */
/* */
/**********************************************************************/
unsigned int ememmax (size)
unsigned int *size;
{
unsigned int status; /* The status of EMM and MEMLIB */
unsigned int num_pages; /* Number of unallocated pages */
unsigned int page; /* Directory page to map in */
unsigned int index; /* Index into a directory page */
unsigned int saved; /* whether the context was saved */
/**********************************************/
/* Call prepare_dir_mapping() to save context */
/* before mapping in the directory */
/**********************************************/
status = prepare_dir_mapping (&saved);
if (status == PASSED)
{
/***************************************************************/
/* If more than 64K worth of unallocated pages, set max to */
/* the largest allocateable block (64K-1). Otherwise, test */
/* the number of unallocated pages * 16K against *size. */
/***************************************************************/
status = get_unalloc_page_count (&num_pages);
if (status == PASSED)
{
if (num_pages >= MAX_ALLOCATABLE_PAGES)
*size = LARGEST_ALLOCATABLE_BLOCK;
else
*size = PAGE_SIZE * num_pages;
}
}
/**************************************/
/* Go through all the directory pages */
/**************************************/
for (page = 0; ((status == PASSED) &&
(page < dir_page_count)); page++)
{
/***********************************/
/* Map in the this directory page. */
/***********************************/
status = map_dir_page (page, FIRST_PHYS_PAGE);
if (status == PASSED)
{
/********************************/
/* Find the maximum free block. */
/********************************/
for (index = 0; index < DIR_ENTRIES_PER_PAGE; index++)
{
if ((directory[0][index].token == UNASSIGNED_TOKEN) &&
(directory[0][index].size > *size))
*size = directory[0][index].size;
}
}
}
/**************************************************************/
/* Unmap the directory - remap the pages that were in before. */
/**************************************************************/
if (saved)
status = restore_memlib_context (status);
/*************************************/
/* If some error return a size of 0. */
/*************************************/
if (status != PASSED)
*size = 0;
return (status);
} /** end of ememmax **/
/*$PAGE*/
/**********************************************************************/
/* */
/* Name: unsigned int emsize (token, *size) */
/* unsigned int token; */
/* unsigned int *size; */
/* */
/* Description: */
/* Returns the size, in bytes, of the allocated block of */
/* memory identified by 'token.' (A token returned from */
/* efmalloc). */
/* */
/* Parameters: */
/* input token identifies the block desired */
/* output size the size, in bytes, of the block */
/* */
/* Results returned: */
/* PASSED Operation successful */
/* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
/* */
/* Calling sequence: */
/* #include "memlib.h" */
/* #include "errors.h" */
/* ... */
/* unsigned int status; */
/* unsigned int token; */
/* unsigned int size; */
/* */
/* status = efmalloc (200, &token); */
/* ... */
/* status = emsize (token, &size); */
/* if (status == PASSED) */
/* printf ("Size of block = %u bytes\n", size); */
/* */
/* Calls: prepare_dir_mapping() */
/* map_dir_page() */
/* check_token() */
/* restore_memlib_context() */
/* */
/* Called by: Application */
/* */
/* Globals referenced/modified: directory */
/* */
/**********************************************************************/
unsigned int emsize (token, size)
unsigned int token;
unsigned int *size;
{
unsigned int status; /* The status of EMM and MEMLIB */
unsigned int page; /* Directory page to map in */
unsigned int index; /* The index into a directory page */
unsigned int context_saved; /* Whether the context was saved */
/**********************************************/
/* Call prepare_dir_mapping() to save context */
/* before mapping in the directory */
/**********************************************/
status = prepare_dir_mapping (&context_saved);
/***************************/
/* Check for a valid token */
/***************************/
if (status == PASSED)
status = check_token (token);
if (status == PASSED)
{
/*****************************************************/
/* Set 'page' to the directory page this token is in */
/*****************************************************/
page = token / DIR_ENTRIES_PER_PAGE;
/**********************************************/
/* Convert the token into an index that falls */
/* within the size of a directory page */
/**********************************************/
index = token % DIR_ENTRIES_PER_PAGE;
/******************************/
/* Map in this directory page */
/******************************/
status = map_dir_page (page, FIRST_PHYS_PAGE);
if (status == PASSED)
{
/*****************************/
/* Check size for this index */
/*****************************/
if (directory[0][index].token == token)
{
*size = directory[0][index].size;
status = PASSED;
}
else
{
*size = 0;
status = INVALID_TOKEN;
}
}
}
/*************************************************************/
/* Unmap the directory - remap the pages that were in before */
/*************************************************************/
if (context_saved)
status = restore_memlib_context (status);
/************************************/
/* If some error return a size of 0 */
/************************************/
if (status != PASSED)
*size = 0;
return (status);
} /** end of emsize **/
/*$PAGE*/
/**********************************************************************/
/* */
/* Name: unsigned int efmalloc (size, token); */
/* unsigned int size; */
/* unsigned int *token; */
/* */
/* Description: */
/* This function is analagous to fmalloc except it allocates a */
/* block of memory from the expanded memory pool. */
/* */
/* Parameters: */
/* input size The desired size, in bytes, of the block of */
/* memory. */
/* output token A tag needed for subsequent calls to the C */
/* Memory Manager to unquiely identify the */
/* block of memory allocated. */
/* */
/* Results returned: */
/* PASSED Operation successful */
/* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
/* */
/* Calling sequence: */
/* #include "memlib.h" */
/* #include "errors.h" */
/* ... */
/* unsigned int token; */
/* unsigned int size; */
/* unsigned int status */
/* ... */
/* size = 100; */
/* status = efmalloc (size, &token); */
/* if (status == PASSED) */
/* { continue normal code - we have allocated space to } */
/* { store 100 byte values } */
/* else */
/* { error condition } */
/* */
/* Calls: allocate_new_block() */
/* check_best_fit() */
/* prepare_dir_mapping() */
/* restore_memlib_context() */
/* split_block() */
/* map_dir_page() */
/* */
/* Called by: Application */
/* */
/* Globals reference/modified: directory */
/* directory_map */
/* */
/**********************************************************************/
unsigned int efmalloc (size, token)
unsigned int size;
unsigned int *token;
{
unsigned int found_block; /* memory block found */
unsigned int status; /* Status of EMM and MEMLIB */
unsigned int best_indexs_page; /* best_index's dir entry's log page */
unsigned int best_indexs_index; /* best_index's index into its page */
unsigned int best_index; /* Index of the current best fit */
unsigned int context_saved; /* whether the context was saved */
long min_difference; /* Minimum difference - best size */
/**********************************************/
/* Attempting to allocate 0 bytes is an error */
/**********************************************/
if (size > 0)
status = PASSED;
else
status = REQUEST_FOR_ZERO_LENGTH_BLOCK;
/**********************************************/
/* Call prepare_dir_mapping() to save context */
/* before mapping in the directory */
/**********************************************/
if (status == PASSED)
status = prepare_dir_mapping (&context_saved);
if (status == PASSED)
{
/*************************************/
/* check to see if there exists a */
/* "best size" fit in memory blocks. */
/*************************************/
status = check_best_fit (size, &best_index, &min_difference);
/********************************************/
/* If best_index is not an UNASSIGNED_TOKEN */
/* then we found a block. */
/********************************************/
if ((status == PASSED) &&
(best_index != UNASSIGNED_TOKEN))
{
found_block = TRUE;
/****************************************************/
/* We're going to use a free block to put our block */
/* into. First we need to map in the free block's */
/* (best_index) directory entry's logical page. */
/****************************************************/
/******************************************************************/
/* Convert best_index to its respective directory page and index. */
/******************************************************************/
best_indexs_page = best_index / DIR_ENTRIES_PER_PAGE;
best_indexs_index = best_index % DIR_ENTRIES_PER_PAGE;
/***************************************/
/* Map in best_index's directory page. */
/***************************************/
status = map_dir_page (best_indexs_page, FIRST_PHYS_PAGE);
/********************************************************/
/* If the size of the best fit that we found was 0 then */
/* what we found was an unallocated block. Allocate a */
/* a new block. */
/********************************************************/
if (directory[0][best_indexs_index].size == 0)
status = allocate_new_block (size, best_index);
else
{
/******************************************************/
/* When using a previously allocated block we need to */
/* check the size and if any space is left over we */
/* should make a new available block. */
/******************************************************/
if ((status == PASSED) &&
(min_difference != 0))
{
status = split_block (best_index, size);
}
} /** end else **/
} /** end if best_index ... **/
} /** end if passed from prepare_dir_mapping() **/
/********************************************************/
/* We found a block - set the token value and directory */
/* entries. (The directory pointer (offset) is set */
/* either in allocate_new_block or was already valid.) */
/********************************************************/
if (status == PASSED)
{
if (found_block)
{
status = map_dir_page (best_indexs_page, FIRST_PHYS_PAGE);
if (status == PASSED)
{
*token = best_index;
directory[0][best_indexs_index].token = best_index;
directory[0][best_indexs_index].size = size;
}
}
else
{
*token = UNASSIGNED_TOKEN;
if (!found_block)
status = TOO_MANY_DIRECTORY_ENTRIES;
}
}
/*************************************************************/
/* Unmap the directory - remap the pages that were in before */
/*************************************************************/
if (context_saved)
status = restore_memlib_context (status);
return (status);
} /** end efmalloc **/
/*$PAGE*/
/**********************************************************************/
/* */
/* Name: unsigned int effree (token) */
/* unsigned int token; */
/* */
/* Description: */
/* This function frees a block of memory from expanded memory */
/* that was allocated by efmalloc(). */
/* */
/* Parameters: */
/* input token The token returned by efmalloc when this */
/* block was allocated. */
/* */
/* Results returned: */
/* PASSED Operation successful */
/* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
/* */
/* Calling sequence: */
/* #include "memlib.h" */
/* #include "errors.h" */
/* ... */
/* unsigned int token; */
/* unsigned int status; */
/* ... */
/* status = efmalloc (100, &token); */
/* ... */
/* status = efree(token); */
/* if (status == PASSED) */
/* { continue normal code } */
/* else */
/* { error condition } */
/* */
/* Calls: check_if_all_blocks_free() */
/* check_token() */
/* prepare_dir_mapping() */
/* restore_memlib_context() */
/* search_after() */
/* search_before() */
/* map_dir_page() */
/* effreeall() */
/* */
/* Called by: Application */
/* */
/* Globals referenced/modified: directory */
/* dir_start */
/* */
/**********************************************************************/
unsigned int effree (token)
unsigned int token;
{
unsigned int status; /* Status of EMM and MEMLIB */
unsigned int all_blocks_free; /* Whether all blocks are free or not */
unsigned int j; /* Looping variable */
unsigned int usable_entry; /* A usuable directory entry */
unsigned int size_mod_page_size; /* Size of a block MOD PAGE_SIZE */
unsigned int tokens_index; /* Token's index into its log page */
unsigned int tokens_page; /* Token's dir entry's logical page */
unsigned int usable_entrys_index;/* Usable_entry's index into its page */
unsigned int usable_entrys_page; /* Usable_entry's dir entry's log page*/
unsigned int final_entrys_index; /* Final_entry's index into its page */
unsigned int final_entrys_page; /* Final_entry's dir entry's log page */
unsigned int final_entry; /* Directory entry of the final */
/* coalesced block */
unsigned int context_saved; /* Whether the context was saved */
/******************************/
/* Initialize some variables. */
/******************************/
all_blocks_free = FALSE;
context_saved = FALSE;
/******************************/
/* Check for an invalid token */
/******************************/
status = check_token (token);
/**********************************************/
/* Call prepare_dir_mapping() to save context */
/* before mapping in the directory */
/**********************************************/
if (status == PASSED)
status = prepare_dir_mapping (&context_saved);
if (status == PASSED)
{
/************************************************/
/* Convert token to its index and logical page. */
/************************************************/
tokens_index = token % DIR_ENTRIES_PER_PAGE;
tokens_page = token / DIR_ENTRIES_PER_PAGE;
/*******************************/
/* Map in this directory page. */
/*******************************/
status = map_dir_page (tokens_page, FIRST_PHYS_PAGE);
}
if (status == PASSED)
{
/*************************************************/
/* If token does not identify an allocated block */
/* or if its size is zero return an error code. */
/*************************************************/
if ((directory[0][tokens_index].token != token) ||
(directory[0][tokens_index].size == 0))
status = INVALID_TOKEN;
if (status == PASSED)
{
/*******************************************************/
/* Set token to UNASSIGNED_TOKEN showing freed status. */
/*******************************************************/
directory[0][tokens_index].token = UNASSIGNED_TOKEN;
/****************************************************/
/* If this token is less than the current starting */
/* location then set the new starting location used */
/* when searching for free directory entries. */
/****************************************************/
if (token < dir_start)
dir_start = token;
/**********************************/
/* Check if all pages are free. */
/* If not, try to coalesce blocks */
/**********************************/
status = check_if_all_blocks_free (&all_blocks_free);
}
if ((status == PASSED) &&
(all_blocks_free))
{
/*****************************************/
/* We need to restore the context before */
/* the pages and handles. */
/*****************************************/
if (context_saved)
status = restore_memlib_context (status);
if (status == PASSED)
{
context_saved = FALSE;
status = effreeall();
}
}
else if ((status == PASSED) &&
(!all_blocks_free))
{
/*****************************************************/
/* Search for a free block of memory after this free */
/* block to coalesce into one free block. This */
/* makes sure that if there are a number of little */
/* blocks that could actually be put together into */
/* one large block that we do so. */
/*****************************************************/
status = search_after (token, &final_entry, &usable_entry);
/*******************************************************/
/* Search for a free block of memory before this block */
/* to coalesce into one free block. */
/*******************************************************/
if (status == PASSED)
status = search_before (token, &final_entry, &usable_entry);
/**************************************************/
/* Test to see if we coalesced any blocks. If so */
/* we need to check that the coalesced block does */
/* not overlap too many logical pages. */
/**************************************************/
if ((status == PASSED) &&
(final_entry != UNASSIGNED_TOKEN))
{
/*****************************************/
/* Convert final_entry to its respective */
/* directory page and index. */
/*****************************************/
final_entrys_page = final_entry / DIR_ENTRIES_PER_PAGE;
final_entrys_index = final_entry % DIR_ENTRIES_PER_PAGE;
/****************************************/
/* Map in final_entry's directory page. */
/****************************************/
status = map_dir_page (final_entrys_page, FIRST_PHYS_PAGE);
if (status == PASSED)
{
/*******************************************************/
/* We can't have a block taking up more logical pages */
/* than it needs. We always guarantee that a block of */
/* memory take the least amount of logical pages as */
/* possible. If it overlaps too many blocks we need */
/* to break it up. Check the block final_index for */
/* too much overlap. */
/*******************************************************/
size_mod_page_size =
directory[0][final_entrys_index].size % PAGE_SIZE;
if (size_mod_page_size == 0)
size_mod_page_size = PAGE_SIZE;
if ((PAGE_SIZE - directory[0][final_entrys_index].offset) <
size_mod_page_size)
{
/*********************************************************/
/* Convert usable_block to its respective directory page */
/* and index. We're going to map this page into the */
/* second physical page. */
/*********************************************************/
usable_entrys_page = usable_entry / DIR_ENTRIES_PER_PAGE;
usable_entrys_index = usable_entry % DIR_ENTRIES_PER_PAGE;
/****************************************************/
/* Map in usable_block's directory page using the */
/* directory_map's second array element to map this */
/* page in at physical page one while keeping the */
/* block that was coalesced's directory page at */
/* physical page zero. */
/***************************************************/
status = map_dir_page (usable_entrys_page, SECOND_PHYS_PAGE);
/*************************************************/
/* This block overlaps too many logical pages. */
/* We need to break it into two pieces at a */
/* a logical page boundry. Use the usable_block */
/* set when coalescing. */
/*************************************************/
if (status == PASSED)
{
/*************************************************/
/* Set the second block's (usable_entry) size to */
/* the size of the first piece after the first */
/* page boundry of the whole block. */
/*************************************************/
directory[1][usable_entrys_index].size =
directory[0][final_entrys_index].size -
PAGE_SIZE + directory[0][final_entrys_index].offset;
/**************************************/
/* Set the offset of the second block */
/* to start at the page boundry. */
/**************************************/
directory[1][usable_entrys_index].offset = 0;
/***********************************************/
/* Set the logical pages for the second block. */
/***********************************************/
for (j = 0; j < NUM_PAGES (directory[1][usable_entrys_index].size); j++)
{
directory[1][usable_entrys_index].logical_page[j] =
directory[0][final_entrys_index].logical_page[j + 1];
}
/***********************************************/
/* Set the first block size to the amount of */
/* memory before the logical page boundry (the */
/* space before the second block). */
/***********************************************/
directory[0][final_entrys_index].size -=
directory[1][usable_entrys_index].size;
}
} /** end if PAGE_SIZE ... **/
} /** status passed **/
} /** end if final_index ... **/
} /** end if check_of_all_blocks_free **/
} /** end if status passed **/
/*************************************************************/
/* Unmap the directory - remap the pages that were in before */
/*************************************************************/
if ((!all_blocks_free) &&
(context_saved))
status = restore_memlib_context (status);
return (status);
} /** end effree **/
/*$PAGE*/
/**********************************************************************/
/* */
/* Name: unsigned int seteptrs (num_blocks, token, pointer) */
/* unsigned int num_blocks; */
/* unsigned int token[]; */
/* void far* pointer[]; */
/* */
/* Description: */
/* Attempts to map all the pages required by the block(s) of */
/* memory identified by token[]. Returns pointers to each block */
/* that has been mapped in. If the requested block(s) could not */
/* mapped in then we return an error. */
/* */
/* Parameters: */
/* input num_blocks Number of blocks to get access */
/* to. */
/* input token[num_blocks] An array of tokens that identify */
/* the blocks to be mapped in. (The */
/* tokens returned by efmalloc when */
/* the block(s) were allocated.) */
/* output pointer[num_blocks] An array of far pointers returned*/
/* to the application. Pointer[i] */
/* will point to the block of */
/* memory identified by token[i]. */
/* */
/* Results returned: */
/* PASSED Operation successful */
/* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
/* */
/* Calling sequence: */
/* #include "memlib.h" */
/* #include "errors.h" */
/* ... */
/* void far* pointers[2]; */
/* unsigned int tokens[2]; */
/* unsigned int status; */
/* ... */
/* status = efmalloc (200, &token[0]); */
/* if (status != PASSED) */
/* { error condition } */
/* else */
/* { continue normal code } */
/* ... */
/* status = efmalloc (600, &token[1]); */
/* if (status != PASSED) */
/* { error condition } */
/* else */
/* { continue normal code } */
/* ... */
/* status = seteptrs (2, tokens, pointers) */
/* if (status == PASSED) */
/* { blocks mapped in - use pointers to reference them } */
/* else */
/* { error - a token was bad or not all blocks could fit } */
/* */
/* Calls: map_dir_page() */
/* map_unmap_pages() */
/* */
/* Called by: Application */
/* set1eptr() */
/* set2eptrs() */
/* set3eptrs() */
/* */
/* Globals referenced/modified: directory */
/* app_handle */
/* directory_map */
/* num_pages_in_page_frame */
/* number_pages_mapped */
/* page_frame_base_address */
/* pages_mapped */
/* */
/**********************************************************************/
unsigned int seteptrs (num_blocks, token, pointer)
unsigned int num_blocks;
unsigned int token[];
void far* pointer[];
{
unsigned int status; /* Status of EMM & MEMLIB */
unsigned int i; /* looping variable */
unsigned int j; /* looping variable */
unsigned int start_phys_page; /* Starting physical page in page frame */
unsigned int log_page_match; /* Match was found? TRUE/FALSE */
unsigned int log_page; /* temporarily store log page we're on */
unsigned int current_dir_page; /* The current directory page mapped in */
unsigned int tokens_page; /* Token's dir entry's logical page */
unsigned int tokens_index; /* Token's index into its logical page */
unsigned int num_pages_for_token;/* Number of logical pages for token's */
/* block */
void far* tokens_ptr; /* pointer to token's block */
/*******************************/
/* Initialize local variables. */
/*******************************/
status = PASSED;
current_dir_page = UNMAPPED;
/***************************************/
/* Make sure all the tokens are valid. */
/***************************************/
for (i = 0; ((status == PASSED) &&
(i < num_blocks)); i++)
{
status = check_token (token[i]);
}
if (status == PASSED)
{
/*******************************************************/
/* Set each page in the page frame to UNMAPPED status. */
/*******************************************************/
for (i = 0; i < num_pages_in_page_frame; i++)
pages_mapped[i].log_page = UNMAPPED;
number_pages_mapped = 0;
/***********************************************/
/* For each block requested, try to map it in. */
/***********************************************/
for (i = 0; ((status == PASSED) &&
(i < num_blocks)); i++)
{
tokens_page = token[i] / DIR_ENTRIES_PER_PAGE;
tokens_index = token[i] % DIR_ENTRIES_PER_PAGE;
if (tokens_page != current_dir_page)
{
current_dir_page = tokens_page;
status = map_dir_page (current_dir_page, FIRST_PHYS_PAGE);
}
if ((status == PASSED) &&
(token[i] != directory[0][tokens_index].token))
status = INVALID_TOKEN;
if (status == PASSED)
{
/*********************************/
/* Initialize variable for loop. */
/*********************************/
start_phys_page = 0;
log_page_match = FALSE;
num_pages_for_token = NUM_PAGES (directory[0][tokens_index].size);
/***********************************************************/
/* While there's potentially room to map the logical pages */
/* need for the i'th block and it isn't already mapped in. */
/***********************************************************/
while (((start_phys_page + num_pages_for_token)
<= num_pages_in_page_frame)
&& (!log_page_match))
{
/*****************************************/
/* Assume the logical pages need for the */
/* i'th block are already mapped in. */
/*****************************************/
log_page_match = TRUE;
/**************************************************/
/* Test each of the logical pages in the i'th */
/* block against the logical pages already mapped */
/* in the page frame starting at start_phys_page. */
/**************************************************/
for (j = 0; (j < num_pages_for_token); j++)
{
log_page = directory[0][tokens_index].logical_page[j];
/**********************************************/
/* We won't have a match if the logical page */
/* we're looking for is not already mapped in */
/* and if the page is unmapped. */
/**********************************************/
if ((log_page != pages_mapped[start_phys_page + j].log_page) &&
(pages_mapped[start_phys_page + j].log_page != UNMAPPED))
log_page_match = FALSE;
}
/*************************************************/
/* If the i'th block isn't mapped in (starting */
/* at start_phys_page) increment start_phys_page */
/* and try again. */
/*************************************************/
if (!log_page_match)
start_phys_page++;
} /** end while **/
/**************************************************/
/* If a match was found set pages_mapped array to */
/* include the logical pages for this block. If */
/* no match was found we can't map this block */
/**************************************************/
if (log_page_match)
{
for (j = 0; (j < num_pages_for_token); j++)
{
pages_mapped[start_phys_page + j].log_page =
directory[0][tokens_index].logical_page[j];
/*************************************************/
/* Update pointer[i] to point to the i'th block. */
/* The offset of the pointer we return is equal */
/* to the offset of this block within the first */
/* logical page for this block. These pointers */
/* are only good modulus 16K since, for example, */
/* we could have allocated a block when it was */
/* mapped in at phys page 0 and now want to map */
/* it in at phys page 3 or some such. */
/*************************************************/
FP_OFF (tokens_ptr) = directory[0][tokens_index].offset;
FP_SEG (tokens_ptr) = FP_SEG(page_frame_base_address) +
start_phys_page * OFFSET_SIZE;
pointer[i] = tokens_ptr;
}
}
else
status = CANNOT_MAP_ALL_BLOCKS;
} /** if status PASSED **/
} /** end for i **/
} /** end if status PASSED **/
/*************************************************************/
/* Unmap the directory - remap the pages that were in before */
/*************************************************************/
if (status == PASSED)
{
/*************************************/
/* Count the number of pages to map. */
/*************************************/
number_pages_mapped = 0;
for (i = 0; i < num_pages_in_page_frame; i++)
{
if (pages_mapped[i].log_page != UNMAPPED)
number_pages_mapped++;
}
/************************************/
/* Map in all the blocks requested. */
/************************************/
status = map_unmap_pages (PHYS_PAGE_MODE, number_pages_mapped,
pages_mapped, app_handle);
}
return(status);
} /** end seteptrs **/
/*$PAGE*/
/**********************************************************************/
/* */
/* Name: unsigned int set1eptr (token, pointer) */
/* unsigned int token; */
/* void far* *pointer; */
/* */
/* Description: */
/* Convenience routine that calls seteptrs to just get access */
/* to one block. */
/* */
/* Parms Passed: */
/* input token A token that identifies the block to be */
/* mapped in. (The token returned by efmalloc */
/* when the block was allocated.) */
/* output pointer A far pointer returned to the application. */
/* It will point to the block of memory */
/* identified by token. */
/* */
/* Results returned: */
/* PASSED Operation successful */
/* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
/* */
/* Calling sequence: */
/* #include "memlib.h" */
/* #include "errors.h" */
/* ... */
/* void far* pointer; */
/* unsigned int token; */
/* unsigned int status; */
/* ... */
/* status = efmalloc (500, &token); */
/* if (status != PASSED) */
/* { error condition } */
/* else */
/* { continue normal code } */
/* ... */
/* status = set1eptr(token, &pointer) */
/* if (status == PASSED) */
/* { block mapped in - use pointer to reference it } */
/* else */
/* { error - the token was invalid } */
/* */
/* Calls: seteptrs() */
/* */
/* Called by: Application */
/* */
/* Globals referenced/modified: None */
/* */
/**********************************************************************/
unsigned int set1eptr (token, pointer)
unsigned int token;
void far* *pointer;
{
unsigned int tokens[1]; /* Set one array entry to pass to */
/* seteptrs() */
void far* pointers[1]; /* Set one array entry to be passed */
/* back from seteptrs() */
unsigned int status; /* Status of EMM and MEMLIB */
tokens[0] = token;
/**************************************************/
/* Call seteptrs() to map in the block identified */
/* by token and return it pointer. */
/**************************************************/
status = seteptrs (1, tokens, pointers);
if (status == PASSED)
*pointer = pointers[0];
return (status);
} /** end set1eptr **/
/*$PAGE*/
/**********************************************************************/
/* */
/* Name: unsigned int set2eptrs (token1, token2, pointer1, */
/* pointer2) */
/* unsigned int token1; */
/* unsigned int token2; */
/* void far* *pointer1; */
/* void far* *pointer2; */
/* */
/* Description: */
/* Convenience routine that calls seteptrs to get access to */
/* two different blocks of memory at one time. */
/* */
/* Parameters: */
/* input token1 A token that identifies the first block to */
/* be mapped in. (The token returned by */
/* efmalloc when the block was allocated.) */
/* input token2 A token that identifies the second block */
/* to be mapped in. (The token returned by */
/* efmalloc when the block was allocated.) */
/* output pointer1 A far pointer returned to the application. */
/* It will point to the block of memory */
/* identified by token1. */
/* output pointer2 A far pointer returned to the application. */
/* It will point to the block of memory */
/* identified by token2. */
/* */
/* Results returned: */
/* PASSED Operation successful */
/* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
/* */
/* Calling sequence: */
/* #include "memlib.h" */
/* #include "errors.h" */
/* ... */
/* void far* ptr1; */
/* void far* ptr2; */
/* unsigned int token1; */
/* unsigned int token2; */
/* unsigned int status; */
/* ... */
/* status = efmalloc (500, &token1); */
/* if (status != PASSED) */
/* { error condition } */
/* else */
/* { continue normal code } */
/* ... */
/* status = efmalloc (900, &token2); */
/* if (status != PASSED) */
/* { error condition } */
/* else */
/* { continue normal code } */
/* ... */
/* status = set2eptrs (token1, token2, &ptr1, &ptr2); */
/* if (status == PASSED) */
/* { blocks mapped in - use pointers to reference them } */
/* else */
/* { error - a token was invalid or blocks couldn't fit } */
/* */
/* Calls: seteptrs() */
/* */
/* Called by: Application */
/* */
/* Globals referenced/modified: None */
/* */
/**********************************************************************/
unsigned int set2eptrs (token1, token2, pointer1, pointer2)
unsigned int token1;
unsigned int token2;
void far* *pointer1;
void far* *pointer2;
{
unsigned int tokens[2]; /* Set two array entries to pass to */
/* seteptrs() */
void far* pointers[2]; /* Set two array entries to be passed */
/* back from seteptrs() */
unsigned int status; /* Status of EMM and MEMLIB */
tokens[0] = token1;
tokens[1] = token2;
/***************************************************/
/* Call seteptrs() to map in the blocks identified */
/* by token1 and token2 and return their pointers. */
/***************************************************/
status = seteptrs (2, tokens, pointers);
if (status == PASSED)
{
*pointer1 = pointers[0];
*pointer2 = pointers[1];
}
return (status);
} /** end set2eptrs **/
/*$PAGE*/
/**********************************************************************/
/* */
/* Name: unsigned int set3eptrs (token1, token2, token3, */
/* pointer1, pointer2, pointer3) */
/* unsigned int token1; */
/* unsigned int token2; */
/* unsigned int token3; */
/* void far* *pointer1; */
/* void far* *pointer2; */
/* void far* *pointer3; */
/* */
/* Description: */
/* Convenience routine that calls seteptrs to get access to */
/* three different blocks of memory at one time. */
/* */
/* Parameters: */
/* input token1 A token that identifies the first block to */
/* be mapped in. (The token returned by */
/* efmalloc when the block was allocated.) */
/* input token2 A token that identifies the second block */
/* to be mapped in. (The token returned by */
/* efmalloc when the block was allocated.) */
/* input token3 A token that identifies the third block to */
/* be mapped in. (The token returned by */
/* efmalloc when the block was allocated.) */
/* output pointer1 A far pointer returned to the application. */
/* It will point to the block of memory */
/* identified by token1. */
/* output pointer2 A far pointer returned to the application. */
/* It will point to the block of memory */
/* identified by token2. */
/* output pointer3 A far pointer returned to the application. */
/* It will point to the block of memory */
/* identified by token3. */
/* */
/* Results returned: */
/* PASSED Operation successful */
/* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
/* */
/* */
/* Calling sequence: */
/* #include "memlib.h" */
/* #include "errors.h" */
/* ... */
/* void far* ptr1; */
/* void far* ptr2; */
/* void far* ptr3; */
/* unsigned int tok1; */
/* unsigned int tok2; */
/* unsigned int tok3; */
/* unsigned int status; */
/* ... */
/* status = efmalloc (500, &tok1); */
/* if (status != PASSED) */
/* { error condition } */
/* else */
/* { continue normal code } */
/* ... */
/* status = efmalloc (900, &tok2); */
/* if (status != PASSED) */
/* { error condition } */
/* else */
/* { continue normal code } */
/* ... */
/* status = efmalloc (300, &tok3); */
/* if (status != PASSED) */
/* { error condition } */
/* else */
/* { continue normal code } */
/* ... */
/* status = set3eptrs (tok1, tok2, tok3, &ptr1, &ptr2, &ptr3); */
/* if (status == PASSED) */
/* { blocks mapped in - use pointers to reference them } */
/* else */
/* { error - a token was invalid or blocks couldn't fit } */
/* */
/* Calls: seteptrs() */
/* */
/* Called by: Application */
/* */
/* Globals referenced/modified: None */
/* */
/**********************************************************************/
unsigned int set3eptrs (token1, token2, token3, pointer1, pointer2,
pointer3)
unsigned int token1;
unsigned int token2;
unsigned int token3;
void far* *pointer1;
void far* *pointer2;
void far* *pointer3;
{
unsigned int tokens[3]; /* Set three array entries to pass */
/* seteptrs() */
void far* pointers[3]; /* Set three array entries to be */
/* passed back from seteptrs() */
unsigned int status; /* Status of EMM and MEMLIB */
tokens[0] = token1;
tokens[1] = token2;
tokens[2] = token3;
/*********************************************************/
/* Call seteptrs() to map in the blocks identified by */
/* token1, token2, and token3 and return their pointers. */
/*********************************************************/
status = seteptrs (3, tokens, pointers);
if (status == PASSED)
{
*pointer1 = pointers[0];
*pointer2 = pointers[1];
*pointer3 = pointers[2];
}
return (status);
} /** end set3eptrs **/
/*$PAGE*/
/**********************************************************************/
/* */
/* Name: unsigned int push_context (void) */
/* */
/* Description: */
/* Pushes the current mapping context onto an internal stack. */
/* The routine pop_context() can be used to restore the context */
/* saved by this routine. Note that for each push we do we must */
/* do a pop. */
/* */
/* Parameters: None */
/* */
/* Results returned: */
/* PASSED Operation successful */
/* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
/* */
/* Calling sequence: */
/* #include "memlib.h" */
/* #include "errors.h" */
/* ... */
/* unsigned int status; */
/* ... */
/* status = push_context(); */
/* if (status == PASSED) */
/* { continue normal code } */
/* else */
/* { error condition } */
/* */
/* Calls: get_partial_context() */
/* init_exp_mem() */
/* */
/* Called by: Application */
/* */
/* Globals referenced/modified: context_ptrs */
/* context_size */
/* exp_initialized */
/* partial_page_map */
/* context_top */
/* */
/**********************************************************************/
unsigned int push_context (void)
{
unsigned int status; /* The status of EMM and MELIB */
/**************************/
/* Assume this will pass. */
/**************************/
status = PASSED;
/*************************************************************/
/* Initialize expanded memory if we haven't already done so. */
/*************************************************************/
if (!exp_initialized)
status = init_exp_mem();
if (status == PASSED)
{
/**************************************/
/* Increment our variable for keeping */
/* track of top of our context stack. */
/**************************************/
context_top++;
/***********************************************************/
/* We have an array of pointers that keep track of the */
/* saved context. Make sure we stay with our array limit. */
/***********************************************************/
if (context_top < MAX_CONTEXTS_AVAILABLE)
{
/***************************************************************/
/* Allocate space in conventional memory to save this context. */
/* Then call get_partial_page_map to do the actual save. */
/***************************************************************/
context_ptrs[context_top] = (CONTEXT_STRUCT *) malloc (context_size);
/*************************************************/
/* Make sure we have enough conventional memory. */
/*************************************************/
if (context_ptrs[context_top] == NULL)
status = MALLOC_FAILURE;
else
status = get_partial_context (&partial_page_map,
context_ptrs[context_top]);
}
else
status = MAX_PUSH_CONTEXTS_EXCEEDED;
/*************************************************/
/* If status failed, reset top of context stack. */
/*************************************************/
if (status != PASSED)
context_top--;
}
return (status);
} /** end push_context **/
/*$PAGE*/
/**********************************************************************/
/* */
/* Name: unsigned int pop_context (void) */
/* */
/* Description: */
/* Pops the last context saved by a call to push_context(). */
/* Note that for each push we do we must do a pop. */
/* */
/* Parameters: None */
/* */
/* Results returned: */
/* PASSED Operation successful */
/* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
/* */
/* Calling sequence: */
/* #include "memlib.h" */
/* #include "errors.h" */
/* ... */
/* unsigned int status; */
/* ... */
/* status = pop_context(); */
/* if (status == PASSED) */
/* { continue normal code } */
/* else */
/* { error condition } */
/* */
/* Calls: set_partial_context() */
/* init_exp_mem() */
/* */
/* Called by: Application */
/* */
/* Globals referenced/modified: context_ptrs */
/* exp_initialized */
/* context_top */
/* */
/**********************************************************************/
unsigned int pop_context (void)
{
unsigned int status; /* The status of EMM and MEMLIB) */
/**************************/
/* Assume this will pass. */
/**************************/
status = PASSED;
/*************************************************************/
/* Initialize expanded memory if we haven't already done so. */
/*************************************************************/
if (!exp_initialized)
status = init_exp_mem();
if (status == PASSED)
{
/********************************************/
/* Make sure there is a context to restore. */
/********************************************/
if (context_top != NO_CONTEXTS)
{
/*********************************************************/
/* Save the context using set_partial_context(), storing */
/* the information an our stack (context_ptrs array). */
/*********************************************************/
status = set_partial_context (context_ptrs[context_top]);
if (status == PASSED)
/**************************************************************/
/* Free the conventional memory we used to save this context. */
/**************************************************************/
free (context_ptrs[context_top]);
}
else
status = NO_CONTEXT_AVAILABLE_TO_POP;
/**********************************************/
/* If status passed, decrement stack pointer. */
/**********************************************/
if (status == PASSED)
if (context_top > 0)
context_top--;
else
context_top = NO_CONTEXTS;
}
return (status);
} /** end pop_context **/
/*$PAGE*/
/**********************************************************************/
/* */
/* Name: unsigned int effreeall (void) */
/* */
/* Description: */
/* Frees all handles, pages and blocks. Prepare for program */
/* termination. */
/* */
/* Parameters: None */
/* */
/* Results returned: */
/* PASSED Operation successful */
/* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
/* */
/* Calling sequence: */
/* #include "memlib.h" */
/* #include "errors.h" */
/* */
/* unsigned int status; */
/* ... */
/* status = effree(); */
/* if (status == PASSED) */
/* { continue normal code } */
/* else */
/* { error condition } */
/* */
/* Calls: dealloc_pages() */
/* map_umap_page() */
/* */
/* Called by: Application */
/* effree() */
/* */
/* Globals referenced/modified: app_handle */
/* exp_initialized */
/* man_handle */
/* num_pages_in_page_frame */
/* context_ptrs */
/* context_top */
/* */
/**********************************************************************/
unsigned int effreeall (void)
{
unsigned int status; /* The status of EMM and MEMLIB */
unsigned int j; /* Looping variable */
status = PASSED;
/*****************************************************************/
/* If MEMLIB has not been initialized no need to free anything. */
/*****************************************************************/
if (exp_initialized)
{
/**************************************/
/* Unmap all pages in the page frame. */
/**************************************/
for (j = 0; (status == PASSED) &&
(j < num_pages_in_page_frame); j++)
{
status = map_unmap_page(j, UNMAPPED, man_handle);
}
if (status == PASSED)
{
/***********************************************/
/* Deallocate the pages and handle for MEMLIB. */
/***********************************************/
status = dealloc_pages (man_handle);
}
if (status == PASSED)
{
/********************************************************/
/* Deallocate the pages and handle for the application. */
/********************************************************/
status = dealloc_pages (app_handle);
/***********************************/
/* Reset exp_initialized to FALSE. */
/***********************************/
if (status == PASSED)
{
exp_initialized = FALSE;
/***********************************************/
/* Free up all space taken by pushed contexts. */
/***********************************************/
if (context_top != NO_CONTEXTS)
{
for (j = 0; j < context_top; j++)
{
if (context_ptrs[j] != NULL)
free (context_ptrs[j]);
}
}
}
}
}
return(status);
} /** end effreeall **/